﻿/// ZaxControls
/// Programmed by Leland Ede
/// Website: http://www.zaxisstudios.com
/// E-Mail: codeplex@zaxis-studios.com
/// Create: 3/29/2014
/// Modified: 4/09/2014

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

using ZaxLib.Imaging;
using ZaxLib.Web.Writers;
using ZaxLib.Web.Writers.Nodes;

namespace ZaxLib.Web.UI.WebControls
{
	[DefaultProperty("Text")]
	[ToolboxData("<{0}:NcjControl runat=server></{0}:NcjControl>")]
	[ToolboxItem(false)]
	public class ZaxControl : WebControl, IPostBackDataHandler, IPostBackEventHandler
	{
		#region ENUM Definitions

		protected enum LabelType
		{
			LT_NONE,
			LT_TOP,
			LT_LEFT,
			LT_RIGHT,
			LT_BOTTOM
		}

		protected enum ItemPos
		{
			IP_NONE,
			IP_RIGHT,
			IP_LEFT,
			IP_TOP,
			IP_BOTTOM,
			IP_AFTERLABEL,
			IP_BEFORELABEL
		}

		#endregion

		#region Parameters
		private bool _isPostback = false;
		[Browsable(false)]
		protected bool IsPostback
		{
			get
			{
				return _isPostback;
			}
			set
			{
				_isPostback = value;
			}
		}

		[Bindable(true)]
		[Category("Appearance")]
		[DefaultValue("")]
		[Localizable(true)]
		public String Label
		{
			get
			{
				String s = ViewState["Label"] as String;
				return (s == null ? String.Empty : s);
			}
			set
			{
				ViewState["Label"] = value;
			}
		}

		[Browsable(false)]
		protected LabelType lblType = LabelType.LT_LEFT;

		[Bindable(true)]
		[Category("Appearance")]
		[DefaultValue("")]
		[Localizable(true)]
		public override String CssClass
		{
			get
			{
				String s = ViewState["CssClass"] as String;
				return (s == null ? String.Empty : s);
			}
			set
			{
				ViewState["CssClass"] = value;
			}
		}

		[Bindable(true)]
		[Category("Appearance")]
		[DefaultValue("")]
		[Localizable(true)]
		public String Help
		{
			get
			{
				String s = ViewState["Help"] as String;
				return (s == null ? String.Empty : s);
			}
			set
			{
				ViewState["Help"] = value;
			}
		}

		[Bindable(true)]
		[Category("Appearance")]
		[DefaultValue("")]
		[Localizable(true)]
		public String HelpSrc
		{
			get
			{
				String s = ViewState["HelpSrc"] as String;
				return (s == null ? String.Empty : s);
			}
			set
			{
				ViewState["HelpSrc"] = value;
			}
		}

		[Bindable(true)]
		[Category("Appearance")]
		[DefaultValue("")]
		[Localizable(true)]
		public String HelpAddr
		{
			get
			{
				String s = ViewState["LinkAddr"] as String;
				return (s == null ? "#" : s);
			}
			set
			{
				ViewState["LinkAddr"] = value;
			}
		}

		[Bindable(true)]
		[Category("Appearance")]
		[DefaultValue("Modal")]
		[Localizable(true)]
		[Description("HelpType - Modal, Non-Modal")]
		public String HelpType
		{
			get
			{
				String s = ViewState["HelpType"] as String;
				return (s == null ? "Non-Modal" : s);
			}
			set
			{
				ViewState["HelpType"] = value;
			}
		}// End parameter HelpType


		[Bindable(true)]
		[Category("Appearance")]
		[DefaultValue("Right")]
		[Localizable(true)]
		public String HelpPosition
		{
			get
			{
				String s = ViewState["HelpPosition"] as String;
				return (s == null ? "Right" : s);
			}
			set
			{
				ViewState["HelpPosition"] = value;
			}
		}

		[Browsable(false)]
		protected ItemPos HelpPos
		{
			get
			{
				return ConvertPosition(HelpPosition);
			}
		}

		[Browsable(false)]
		private ItemPos ConvertPosition(String value)
		{
			ItemPos pos = ItemPos.IP_NONE;
			switch (value.ToUpper())
			{
				case "RIGHT":
					pos = ItemPos.IP_RIGHT;
					break;
				case "LEFT":
					pos = ItemPos.IP_LEFT;
					break;
				case "TOP":
					pos = ItemPos.IP_TOP;
					break;
				case "BOTTOM":
					pos = ItemPos.IP_BOTTOM;
					break;
				case "BEFORELABEL":
					pos = ItemPos.IP_BEFORELABEL;
					break;
				case "LABEL":
				case "AFTERLABEL":
					pos = ItemPos.IP_AFTERLABEL;
					break;
			}
			return pos;
		}

		[Bindable(true)]
		[Category("Data")]
		[DefaultValue("")]
		[Localizable(true)]
        public String Text
        {
            get
            {
                String s = ViewState["Text"] as String;
                return (s == null ? String.Empty : s);
            }
            set
            {
                ViewState["Text"] = value;
            }
        }

		[Bindable(false)]
		[Category("Required")]
		[DefaultValue("False")]
		[Localizable(true)]
		public bool Required
		{
			get
			{
				bool b = Convert.ToBoolean(ViewState["Required"]);
				return b;
			}
			set
			{
				ViewState["Required"] = value;
			}
		}// End parameter Required

		[Bindable(false)]
		[Category("Required")]
		[DefaultValue("General")]
		[Localizable(true)]
		public String RequiredType
		{
			get
			{
				String s = ViewState["RequiredType"] as String;
				return (s == null ? "General" : s);
			}
			set
			{
				ViewState["RequiredType"] = value;
			}
		}// End parameter RequiredType

		[Bindable(false)]
		[Category("Required")]
		[DefaultValue("required")]
		[Localizable(true)]
		public String RequiredClass
		{
			get
			{
				String s = ViewState["RequiredClass"] as String;
				return (s == null ? "required" : s);
			}
			set
			{
				ViewState["RequiredClass"] = value;
			}
		}// End parameter RerquiredClass

		[Bindable(false)]
		[Category("Required")]
		[DefaultValue("BeforeLabel")]
		[Localizable(true)]
		public String RequiredPosition
		{
			get
			{
				String s = ViewState["RequiredPosition"] as String;
				return (s == null ? "BeforeLabel" : s);
			}
			set
			{
				ViewState["RequirePosition"] = value;
			}
		}

		[Browsable(false)]
		protected ItemPos ReqPos
		{
			get
			{
				return ConvertPosition(RequiredPosition);
			}
		}

		private bool _isRequired = false;
		[Browsable(false)]
		public bool IsRequired
		{
			get
			{
				return _isRequired;
			}
			set
			{
				_isRequired = value;
			}
		}// End parameter IsRequired

        #endregion

		#region Control Writers

        /// <summary>
        /// Perform all pre writing code of control
        /// </summary>
        /// <param name="writer">Output object provided by web server</param>
        protected virtual void PreWrite(HtmlTextWriter writer)
		{
			if (HelpPos == ItemPos.IP_LEFT)
			{
				HelpWrite(writer);
			}// Endif HelpPos is IP_LEFT
			if (ReqPos == ItemPos.IP_BEFORELABEL)
			{
				RequiredWrite(writer);
			}// Endif ReqPos is IP_BEFORELABEL

			// Check if label is drawn at this stage
			if (lblType == LabelType.LT_LEFT || lblType == LabelType.LT_TOP)
			{
				LabelWrite(writer);
			}// Endif lblType is drawn at this stage check

			if (ReqPos == ItemPos.IP_AFTERLABEL)
			{
				RequiredWrite(writer);
			}
		}// End method PreWrite

        /// <summary>
        /// Write main control code in this method
        /// </summary>
        /// <param name="writer">Output object provided by web server</param>
        protected virtual void ControlWrite(HtmlTextWriter writer)
		{

		}

        /// <summary>
        /// Perform any post witting of the control
        /// </summary>
        /// <param name="writer">Output object provided by web server</param>
		protected virtual void PostWrite(HtmlTextWriter writer)
		{
			if (HelpPos == ItemPos.IP_RIGHT)
			{
				HelpWrite(writer);
			}
			if (HelpPos == ItemPos.IP_BOTTOM)
			{
				writer.RenderBeginTag(HtmlTextWriterTag.Div);
				HelpWrite(writer);
				writer.RenderEndTag();
			}// End if Help Position set to bottom
		}// End method PostWrite

		/// <summary>
		/// Write help controls
		/// </summary>
		/// <param name="writer">Html text writer for control</param>
		protected virtual void HelpWrite(HtmlTextWriter writer)
		{
			// Add help information for this tag
			if (Help != String.Empty)
			{
				// Create a button id for help popup.
				String ButtonId = String.Format("{0}HelpButton", ID);
				// Check if there is a help image defined
				if (HelpSrc != String.Empty)
				{
					if (HttpContext.Current != null)
					{
						CIcon icon = new CIcon(HelpSrc, HttpContext.Current.Request);
						// Draw HTML Image Tag
						writer.AddAttribute(HtmlTextWriterAttribute.Id, ButtonId);
						writer.AddAttribute(HtmlTextWriterAttribute.Src, icon.WebPath);
						writer.AddAttribute(HtmlTextWriterAttribute.Width, icon.Width);
						writer.AddAttribute(HtmlTextWriterAttribute.Height, icon.Height);
						writer.AddAttribute(HtmlTextWriterAttribute.Border, "0");
						writer.RenderBeginTag(HtmlTextWriterTag.Img);
						writer.RenderEndTag();
						writer.Flush();
					}
				}
				else
				{
					// Create a simple text button
					writer.AddAttribute(HtmlTextWriterAttribute.Id, ButtonId);
					writer.RenderBeginTag(HtmlTextWriterTag.Span);
					writer.Write("?");
					writer.RenderEndTag();
					writer.Flush();
				}

				// Define a unique help ID
				String HelpId = String.Format("{0}ItemHelp", ID);
				String HelpTitle = "Help";
				if (Label.Trim().Length > 0) HelpTitle = String.Format("{0} - {1}", HelpTitle, Label);
				// Create HTML element for help content
				writer.AddAttribute(HtmlTextWriterAttribute.Id, HelpId);
				writer.AddAttribute(HtmlTextWriterAttribute.Title, HelpTitle);
				writer.RenderBeginTag(HtmlTextWriterTag.Div);
				writer.Write(Help);
				writer.RenderEndTag();
				writer.Flush();

				// TODO: Move this to have a defined top node all code uses
				INode top = CodeWriter.CreateTopNode();
				INode node = CodeWriter.CreateReadyFunction();
				INode nTop = CodeWriter.AddChild(HelpId, node).SelectorId();
				CodeWriter.AddChild("dialog").Joined();
				node = CodeWriter.AddParam("").ObjectDef();
				CodeWriter.AddParam("autoOpen", "false", node).VarDef();
				if (HelpType.ToLower().CompareTo("modal") == 0)
				{
					CodeWriter.AddParam("modal", "true").VarDef();
				}

				CodeWriter.AddChild(ButtonId, nTop).SelectorId();
				CodeWriter.AddChild("button").Joined();
				CodeWriter.AddParam("");
				CodeWriter.AddChild("click").Joined();
				node = CodeWriter.AddParam("function").Function();
				CodeWriter.AddChild(HelpId, node).SelectorId();
				CodeWriter.AddChild("dialog").Joined();
				CodeWriter.AddParam("\"open\"");

			}// Endif Help content is defined
		}// End method HelpWrite

		protected virtual void RequiredWrite(HtmlTextWriter writer)
		{
			// Do basic validation
			if (Required && IsPostback && Text.Trim().Length == 0)
			{
				writer.AddAttribute(HtmlTextWriterAttribute.Class, RequiredClass);
				writer.RenderBeginTag(HtmlTextWriterTag.Span);
				writer.Write("*");
				writer.RenderEndTag();
				writer.Flush();
			}
		}

		/// <summary>
		/// Write label of control to requesting client
		/// </summary>
		/// <param name="writer"></param>
		protected virtual void LabelWrite(HtmlTextWriter writer)
		{
			// Add CssClass to label
			if (CssClass != String.Empty)
			{
				writer.AddAttribute(HtmlTextWriterAttribute.Class, CssClass);
			}// Endif CssClass is defined

			switch (lblType)
			{
				case LabelType.LT_LEFT:
				case LabelType.LT_RIGHT:
					writer.RenderBeginTag(HtmlTextWriterTag.Span);
					break;
				case LabelType.LT_BOTTOM:
				case LabelType.LT_TOP:
					writer.RenderBeginTag(HtmlTextWriterTag.Div);
					break;

			}

			writer.Write(Label);
			if (HelpPos == ItemPos.IP_AFTERLABEL)
			{
				HelpWrite(writer);
			}
			writer.RenderEndTag();
			writer.WriteLine();
			writer.Flush();
		}// End method LabelWrite

		#endregion

		#region Render Methods

		protected override void Render(HtmlTextWriter writer)
		{
			base.Render(writer);
		}

		protected override void RenderContents(HtmlTextWriter writer)
		{
			PreWrite(writer);
			writer.Flush();
			ControlWrite(writer);
			writer.Flush();
			PostWrite(writer);
			writer.Flush();
			CodeWriter.Write(writer);
		}

		#endregion

		#region jQuery Management Tools
		private IWriter _codeWriter = null;
		/// <summary>
		/// Object to handle writing the browser code
		/// </summary>
		[Browsable(false)]
		public IWriter CodeWriter
		{
			get
			{
				// Check to see if there a defined code writer
				if (_codeWriter == null) CodeWriter = new JQWriter();

				// Return code writer object
				return _codeWriter;
			}
			set
			{
				_codeWriter = value;
			}
		}// End parameter CodeWriter

		#endregion

        #region Post Back Data Handlers

        public event EventHandler Change;

		[Browsable(false)]
		public bool IsChange
		{
			get
			{
				return Change != null;
			}
		}

        public virtual void OnChange(EventArgs e)
        {
            if (IsChange)
                Change(this, e);
        }

        public virtual bool LoadPostData(String key, NameValueCollection collection)
        {
            // Create default return value
            bool retVal = false;
            String currText = Text;
            String newText = collection[key] as String;
            if (!currText.Equals(newText))
            {
                Text = newText;
                retVal = true;
            }

			IsPostback = true;

            return retVal;
        }

        public virtual void RaisePostDataChangedEvent()
        {
            OnChange(EventArgs.Empty);
        }

		public void RaisePostBackEvent(String eventArgs)
		{
			OnChange(EventArgs.Empty);
		}
		
		#endregion
    }
}
